

import java.io.*;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.*;

public class SSF {

	public static void main(String[] args) {
		try {
			encrypt("MHuebner.pub", "MHuebner.prv", "ITSAufgabe3.pdf","encrypted.pdf");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	public static void encrypt(String publicKeyFile, String privateKeyFile, String inputFile, String outputFile) throws Exception {
		DataInputStream istream_PrivKey		= new DataInputStream(new FileInputStream(privateKeyFile));
		DataInputStream istream_PubKey		= new DataInputStream(new FileInputStream(publicKeyFile));
		DataInputStream istream_InputFile	= new DataInputStream(new FileInputStream(inputFile));
		DataOutputStream ostream_OutputFile	= new DataOutputStream(new FileOutputStream(outputFile));
		
		KeyFactory	rsaFactory			= KeyFactory.getInstance("RSA");
		
		//privKey einlesen (2a)
		int privOwnerLen		= istream_PrivKey.readInt();
		byte[] privOwner		= new byte[privOwnerLen];
		istream_PrivKey.read(privOwner, 0, privOwnerLen);
		int privKeyLen			= istream_PrivKey.readInt();
		byte[]	privKey			= new byte[privKeyLen];
		istream_PrivKey.read(privKey, 0, privKeyLen);
		PrivateKey privKeyObj	= rsaFactory.generatePrivate(new PKCS8EncodedKeySpec(privKey)); 

		//pubKey einlesen (2b)q
		int pubOwnerLen = istream_PubKey.readInt();
		byte[] pubOwner	= new byte[pubOwnerLen];
		istream_PubKey.read(pubOwner, 0, pubOwnerLen);
		int pubKeyLen		= istream_PubKey.readInt();
		byte[] pubKey		= new byte[pubKeyLen];
		istream_PubKey.read(pubKey, 0, pubKeyLen);
		PublicKey pubKeyObj	= rsaFactory.generatePublic(new X509EncodedKeySpec(pubKey));
		
		//generate secretKey AES 128Bit (2c)
		KeyGenerator secretKeyGen	= KeyGenerator.getInstance("AES");
        secretKeyGen.init(128, new SecureRandom());
        SecretKey secretKey			= secretKeyGen.generateKey();
		
		//create Signature for secretKey with privKey and SHA1withRSA (2d)
		Signature secretKeySignatureObj		= Signature.getInstance("SHA1withRSA");
		secretKeySignatureObj.initSign(privKeyObj);
		secretKeySignatureObj.update(secretKey.getEncoded());
		byte[] secretKeySignature			= secretKeySignatureObj.sign();
		
		//enrcryption of secretKey with pubKey RSA (2e)
		Cipher wrappedSecretKeyCipher		= Cipher.getInstance("RSA");
		wrappedSecretKeyCipher.init(Cipher.WRAP_MODE, pubKeyObj);
		byte[] wrappedSecretKey = wrappedSecretKeyCipher.wrap(secretKey);
		
		//read inputFile and encrypt AES + secretKey (2f)
        Cipher encryptedInputCipher			= Cipher.getInstance("AES");
        encryptedInputCipher.init(Cipher.ENCRYPT_MODE, secretKey);
		
		//create outputFile	(2g)
		/*	1:	int		lengthOfEnryptedSecretKey	(2e)
		 * 	2:	byte[]	enryptedSecretKey			(2e)
		 * 	3:	int		lengthOfSecretKeySign		(2d)
		 * 	4:	byte[]	secretKeySign				(2d)
		 * 	5:	byte[]	enryptedInputFile			(2f) 
		 */
		ostream_OutputFile.writeInt(wrappedSecretKey.length);
		ostream_OutputFile.write(wrappedSecretKey);
		ostream_OutputFile.writeInt(secretKeySignature.length);
		ostream_OutputFile.write(secretKeySignature);
		SF_Util.crypt(istream_InputFile, ostream_OutputFile, encryptedInputCipher);
		
		istream_InputFile.close();
		istream_PubKey.close();
		istream_PrivKey.close();
		ostream_OutputFile.close();
    }
}
